package com.starsoft.smdc.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.starsoft.frame.core.orm.PageObject;
import com.starsoft.frame.util.DateUtil;
import com.starsoft.frame.util.MapUtil;
import com.starsoft.frame.util.NumberUtil;
import com.starsoft.smdc.bean.SmdcDiv;
import com.starsoft.smdc.bean.SmdcEr;
import com.starsoft.smdc.bean.SmdcErId;
import com.starsoft.smdc.bean.SmdcSecurity;
import com.starsoft.smdc.dao.DivDao;
import com.starsoft.smdc.dao.ErDao;
import com.starsoft.smdc.dao.SmdcSecurityDao;
import com.starsoft.smdc.util.SecurityDataCombin;
import com.starsoft.smdc.util.SecurityDataCombin.SecurityDataCombinBean;

@Service
public class ErService {
	
	@Autowired
	ErDao erDao;
	
	@Autowired
	DivDao divDao;
	
	@Autowired
	SmdcSecurityDao securityDao;
	
	public void save(SmdcEr er){
		SmdcErId id = er.getId();
		SmdcEr erDb = erDao.get(id);
		if(checkCanUpdate(erDb) == checkCanUpdate(er)){
			if(checkCanUpdate(erDb)){
				MapUtil.updateBean(erDb, MapUtil.toMap(er));
				erDao.saveOrUpdate(erDb);
				SmdcSecurity security = securityDao.get(erDb.getId().getSecId());
				update(security, erDb.getId().getReportDate());
			} else {
				throw new RuntimeException("can not update");
			}
		} else if(checkCanUpdate(erDb) != checkCanUpdate(er)){
			erDb.setNotUpdate(er.getNotUpdate());
			erDao.saveOrUpdate(erDb);
		}
	}
	
	public boolean checkCanUpdate(SmdcEr er){
		return erDao.checkCanUpdate(er);
	}
	
	public void delete(SmdcEr er){
		erDao.delete(er);
	}
	
	public Date getBeginDate(SmdcSecurity security){
		Date beginDate = erDao.getMaxErDate(security);
		if(beginDate == null){
			beginDate = securityDao.getBeginDate(security);
		}else{
			beginDate =DateUtil.getNext(beginDate);
		}
		return beginDate;
	}
	
	public SmdcEr getPbDateBeforeOne(SmdcSecurity security, Date publishDate) {
		return erDao.getPbDateBeforeOne(security, publishDate);
	}
	
	public List<SmdcEr> getPbDateBeforeN(SmdcSecurity security, Date publishDate, int number) {
		return erDao.getPbDateBeforeN(security, publishDate, number);
	}
	
	public void update(SmdcSecurity security, Date beginDate) {
		List<SecurityDataCombinBean> combinBeanList = getSecurityDataCombin(security, beginDate);
		adjShareAssert(combinBeanList);
		updateShareFactor(combinBeanList);
	}

	private void adjShareAssert(List<SecurityDataCombinBean> combinBeanList) {
		List<Integer> erNotNullIndex = new ArrayList<>();
		for (int i = 0; i < combinBeanList.size(); i++) {
			SmdcEr er = combinBeanList.get(i).getEr();
			if (er != null) {
				erNotNullIndex.add(i);
			}
		}
		for (int i = 0; i < erNotNullIndex.size(); i++) {
			int index = erNotNullIndex.get(i);
			SmdcEr er = combinBeanList.get(index).getEr();
			Date erDate = er.getId().getReportDate();
			double shareAssertAdj = 0;
			for (int j = 0; j < combinBeanList.size(); j++) {
				SecurityDataCombinBean combinBean = combinBeanList.get(j);
				SmdcDiv div = combinBean.getDiv();
				if (div == null) {
					continue;
				}
				Date divDate = div.getId().getDivDate();
				Date earingDivDate = div.getEarningDivDate();
				if (earingDivDate != null && !earingDivDate.after(erDate) && divDate.after(erDate)) {
					shareAssertAdj += NumberUtil.null2Zero(div.getPerCashDiv());
				}
			}
			er.setShareAssertAdjDiv(shareAssertAdj);
			er.setShareAssertAdj(shareAssertAdj+er.getShareAssert());
		}
	}
	
	private void updateShareFactor(List<SecurityDataCombinBean> combinBeanList){
		for (int i = 0;i<combinBeanList.size();i++) {
			SecurityDataCombinBean combinBean = combinBeanList.get(i);
			SmdcEr er = combinBean.getEr();
			if(er==null){
				continue;
			}
			for(int j=i;j>=0;j--){
				SmdcDiv div = combinBeanList.get(j).getDiv();
				if(div!=null){
					er.setShareFactor(div.getShareFactor());
					er.setAdjFactor(div.getAdjFactor());
					break;
				}
			}
		}
	}
	
	private List<SecurityDataCombinBean> getSecurityDataCombin(SmdcSecurity security, Date beginDate) {
		List<SmdcEr> erList = erDao.getErDateAfter(security, beginDate);
		List<SmdcDiv> divList = divDao.getDivDateAfter(security, beginDate);
		SmdcDiv div = divDao.getDivDateBeforeOne(security, beginDate);
		if(div!=null){
			divList.add(div);
		}
		SecurityDataCombin dataCombin = new SecurityDataCombin(security);
		dataCombin.combinEr(erList);
		dataCombin.combinDiv(divList);
		return dataCombin.getList();
	}

	@SuppressWarnings("unchecked")
	public Map<String, Object> pageQuery(PageObject po, String secId, Date beginDate, Date endDate) {
		Map<String, Object> result = erDao.pageQuery(po, secId, beginDate, endDate);
		List<SmdcEr> rows = po.getRows();
		if(rows!=null){
			List<Object> newRows = new ArrayList<>();
			for(SmdcEr er:rows){
				newRows.add(this.convertBean(er));
			}
			result.put("rows", newRows);
		}
		return result;
	}

	public Map<String, Object> convertBean(SmdcEr er){
		Map<String, Object> result = MapUtil.toMap(er);
		result.remove("id");
		result.put("reportDate", er.getId().getReportDate());
		result.put("secId", er.getId().getSecId());
		result.put("secName", securityDao.get(er.getId().getSecId()).getSecName());
		return result;
	}

}
